home *** CD-ROM | disk | FTP | other *** search
/ The Game Master (3rd Edition) / The Game Master 3rd edition.iso / files / musieech / mimic11 / mint.asm < prev    next >
Assembly Source File  |  1990-03-13  |  7KB  |  178 lines

  1. ; MINT.ASM  Version 1.0
  2. ; (c) 1990 Eletech Electronics, Inc. All rights UNreserved.
  3. ;
  4. ; Creation : 3-13-90 by Wei Lu.
  5. ; Function : Works with MIMIC.C to play Eletech Digicorder recorded voice
  6. ;            file thru PC's internal speaker at specified sampling rate. 
  7. ; Usage    : See MIMIC.C.
  8. ; Assembler: Microsoft MASM 5.0 and up.
  9. ;            Assembling Options: None.
  10. ;
  11. ; Operation: MINT.ASM is an interrupt handler. After MIMIC.C re-directs clock
  12. ;            interrupt, subsequent timer 0 interrupts are intercepted and
  13. ;            handled by MINT.ASM. 
  14. ;
  15. ;            MINT.ASM has two responsibilities:
  16. ;
  17. ;            a. Output voice data bit by bit to PC's speaker upon each timer
  18. ;               0 interrupt.
  19. ;
  20. ;            b. Maintain DOS clock operation by doing "real" clock interrupts
  21. ;               18.2 times per second.
  22. ;
  23. ;            MINT.ASM assumes that MIMIC.C has done the following setup:
  24. ;
  25. ;            a. Load voice data into play buffer pointed to by play_addr.
  26. ;
  27. ;            b. Calculate and set play_ptr, play_length and tack_count (see
  28. ;               MIMIC.C for explanations.)
  29. ;
  30. ;            c. Re-direct timer 0 (clock) interrupt and re-program timer 0 
  31. ;               interrupt rate to equal sampling rate.
  32. ;
  33. ;            Upon each timer 0 interrupt, MINT.ASM will be activated and do
  34. ;            one of the following:
  35. ;
  36. ;            a. If there is no more data to play, do a "real" clock interrupt
  37. ;               if it's time to, then terminate.
  38. ;
  39. ;            Otherwise,
  40. ;
  41. ;            b. If it does not need a new byte of data, output a bit and
  42. ;               terminate.
  43. ;
  44. ;            c. If it needs a new byte of data but it's not time yet to do a
  45. ;               "real" clock interrupt, get a byte, output a bit and 
  46. ;               terminate.
  47. ;
  48. ;            d. If it needs a new byte of data and it's also time to do a
  49. ;               "real" clock interrupt, get a byte, output a bit, do a "real"
  50. ;               clock interrupt and terminate.
  51. ;
  52. ;            The following codes are written so as to minimize the execution
  53. ;            time of case b above. See MIMIC.C for more operation details.
  54.  
  55. .model small
  56.  
  57. public        _int_handler
  58. public        _play_addr
  59. public        _play_ptr
  60. public        _play_length
  61. public        _tack_count
  62.  
  63. speaker       equ    97                     ; speaker I/O port
  64. ocw2          equ    20h                    ; 8259 control I/O port
  65. eoi           equ    20h                    ; "End Of Interrupt" control word
  66. clock_irq     equ    255                    ; "real" clock new interrupt #
  67.  
  68. .data
  69.  
  70. _play_addr    label  dword                  ; play buffer is 64K bytes
  71. _play_ptr     label  word                   ; actually the offset of play_addr
  72. play_addr     label  dword                  ;   (set and changed by MIMIC.C)
  73. play_addr_off dw     ?
  74. play_addr_seg dw     ?                      ; does not change once set
  75.  
  76. _play_length  label  word                   ; number of bytes to play
  77. play_length   dw     ?
  78.  
  79. _tack_count   label  byte                   ; see MIMIC.C
  80. tack_count    db     ?
  81.  
  82. data_byte     db     55                     ; a byte of garbage doesn't hurt
  83. bit_ptr       db     80h                    ; bits go from left to right
  84. t_count       db     ?                      ; a working copy of tack_count
  85.  
  86. .code
  87.  
  88. _int_handler  proc   far
  89.               push   ax
  90.               push   ds
  91.  
  92.               mov    ax,@data
  93.               mov    ds,ax
  94.               cmp    play_length,0          ; are we out of voice data?
  95.               je     no_more
  96.               mov    al,data_byte
  97.               mov    ah,bit_ptr             ; bit_ptr used as a mask
  98.               and    al,ah                  ; is this bit 0 or 1?
  99.               jz     zero
  100. one:
  101.               nop                           ; so that "one" and "zero" take
  102.               nop                           ; the same amount of time to do
  103.               mov    al,01001010b           ;   (optimized for AT)
  104.               out    speaker,al
  105.               ror    ah,1                   ; will set Carry if rotate around
  106.               mov    bit_ptr,ah             ; update bit_ptr
  107.               jc     adjust
  108.               mov    al,eoi
  109.               out    ocw2,al                ; re-enable interrupt requests
  110.               pop    ds
  111.               pop    ax
  112.               iret
  113. zero:
  114.               mov    al,01001000b
  115.               out    speaker,al
  116.               ror    ah,1
  117.               mov    bit_ptr,ah
  118.               jc     adjust
  119.               mov    al,eoi
  120.               out    ocw2,al
  121.               pop    ds
  122.               pop    ax
  123.               iret
  124. adjust:                                     ; now we have to get a new byte
  125.               sub    play_length,1          ; also update play_length
  126.               push   si
  127.               push   es
  128.               les    si,dword ptr ds:play_addr
  129.               mov    al,byte ptr es:[si]
  130.               mov    data_byte,al           ; the new byte is in
  131.               inc    si
  132.               mov    play_addr_off,si       ; update play_ptr
  133.               dec    t_count                ; is it time to do clock int?
  134.               jz     do_interrupt
  135.               mov    al,eoi
  136.               out    ocw2,al
  137.               pop    es
  138.               pop    si
  139.               pop    ds
  140.               pop    ax
  141.               iret
  142. do_interrupt:
  143.               mov    al,tack_count
  144.               mov    t_count,al             ; reset t_count to tack_count
  145.               int    clock_irq              ; do clock interrupt
  146.               pop    es                     ; no need to re-enable interrupt
  147.               pop    si                     ;   requests since it's already
  148.               pop    ds                     ;   been done in clock interrupt
  149.               pop    ax                     ;   service routine
  150.               iret
  151. no_more:
  152.               ror    bit_ptr,1              ; still have to know when to do 
  153.               jc     adj                    ;   clock interrupt
  154.               mov    al,eoi
  155.               out    ocw2,al
  156.               pop    ds
  157.               pop    ax
  158.               iret
  159. adj:
  160.               dec    t_count
  161.               jz     do_int
  162.               mov    al,eoi
  163.               out    ocw2,al
  164.               pop    ds
  165.               pop    ax
  166.               iret
  167. do_int:
  168.               mov    al,tack_count
  169.               mov    t_count,al
  170.               int    clock_irq
  171.               pop    ds
  172.               pop    ax
  173.               iret
  174.  
  175. _int_handler  endp
  176.  
  177.               end
  178.